/**
 * Class: DPoint2
 *
 * Purpose: 
 *
 * Created: Jan 23, 2010 @ 11:06:19 PM
 * @author Ken Scott
 */
package org.openfantasia.util.math;

import org.openfantasia.util.Copyable;

public class DPoint2 implements Copyable<DPoint2> {

	private static final int N = 2;

	public double p[];


	public DPoint2() {
		p = new double[N];
	}


	public DPoint2(double p0, double p1) {
		p = new double[]{p0, p1};
	}


	public DPoint2(double[] a) {
		if (a.length != N) {
			throw new IllegalArgumentException("Input array must be of length " + N + ", not " + a.length);
		}
		this.p = Math1D.copy(a);
	}


	public DPoint2(DPoint2 pt) {
		this(pt.p);
	}


	public double[] getValue() {
		return p;
	}


	public DPoint2 copy() {
		return new DPoint2(p);
	}

	public void copy(DPoint2 that) {
		p = Math1D.copy(that.p);
	}



	public DPoint2 clear() {
		Math1D.fill(p, 0);
		return this;
	}


	public DPoint2 normalize() {
		double mag = Math1D.mag(p);
		this.p = Math1D.scale(1d / mag, p);
		return this;
	}


	public double dotp(DPoint2 other) {
		return Math1D.dotp(this.p, other.p);
	}


	public DPoint2 mulNoise(double frac) {
		for (int i = 0; i < N; i++) {
			this.p[i] *= PMath.random(frac);
		}
		return this;
	}


	public DPoint2 addNoise(double frac) {
		for (int i = 0; i < N; i++) {
			this.p[i] += PMath.random(frac);
		}
		return this;
	}


	public DPoint2 randomize(double mag) {
		p[0] = PMath.random(-1.0, 1.0);
		p[1] = PMath.random(-1.0, 1.0);
		return normalize().scale(mag);
	}


	public DPoint2 scale(double a) {
		this.p[0] *= a;
		this.p[1] *= a;
		return this;
	}


	public DPoint2 neg() {
		for (int i = 0; i < N; i++) {
			this.p[i] = -this.p[i];
		}
		return this;
	}


	public DPoint2 abs() {
		for (int i = 0; i < N; i++) {
			this.p[i] = Math.abs(this.p[i]);
		}
		return this;
	}


	public DPoint2 add(double... a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.length); i++) {
			this.p[i] += a[i];
		}
		return this;
	}


	public DPoint2 add(DPoint2 a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.p.length); i++) {
			this.p[i] += a.p[i];
		}
		return this;
	}


	public DPoint2 sub(double... a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.length); i++) {
			this.p[i] -= a[i];
		}
		return this;
	}


	public DPoint2 sub(DPoint2 a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.p.length); i++) {
			this.p[i] -= a.p[i];
		}
		return this;
	}


	public DPoint2 mul(double... a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.length); i++) {
			this.p[i] *= a[i];
		}
		return this;
	}


	public DPoint2 mul(DPoint2 a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.p.length); i++) {
			this.p[i] *= a.p[i];
		}
		return this;
	}


	public DPoint2 div(double... a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.length); i++) {
			this.p[i] /= a[i];
		}
		return this;
	}


	public DPoint2 div(DPoint2 a) {
		if(a == null) {
			return this;
		}

		for (int i = 0; i < Math.min(N, a.p.length); i++) {
			this.p[i] /= a.p[i];
		}
		return this;
	}


	public double[] toDouble() {
		return new double[]{p[0], p[1]};
	}


	public float[] toFloat() {
		return new float[]{(float) p[0], (float) p[1]};
	}


	public int[] toInt() {
		return new int[]{(int) p[0], (int) p[1]};
	}


	@Override
	public String toString() {
		return Math1D.toString(p);
	}
}